#pragma once

#include <iostream>
#include <sys/select.h>
#include <sys/epoll.h>
#include <unistd.h>

#include "Common.hpp"
#include "Socket.hpp"
#include "Log.hpp"

using namespace SocketModule;
using namespace LogModule;

class EpollServer
{
    const static int size = 4096;    // fd_set集合的大小
    const static int defaultfd = -1; // 默认文件描述符

public:
    // 构造
    EpollServer(int port) : _listensock(std::make_unique<TcpSocket>()),
                            _isrunning(false), // _listensock 继承子类TcpSocket
                            _epfd(defaultfd)   // 初始化epoll句柄
    {
        _listensock->BindTcpSocketMethod(port); // 绑定端口

        // 创建epoll
        _epfd = epoll_create(128);
        if (_epfd < 0)
        {
            LOG(LogLevel::FATAL) << "epoll_create error, 创建epoll失败, 已退出!";
            exit(EPOLL_CREATE_ERR);
        }
        LOG(LogLevel::INFO) << "epoll_create success, epoll创建成功!  epfd: " << _epfd;

        // 设置关注事件, 关注读事件
        struct epoll_event ev;
        ev.events = EPOLLIN; // 读事件
        ev.data.fd = _listensock->Fd();

        int ret = epoll_ctl(_epfd, EPOLL_CTL_ADD, _listensock->Fd(), &ev); // 注册相关节点到epoll
        if (ret < 0)
        {
            LOG(LogLevel::FATAL) << "epoll_ctl error, 注册监听套接字到epoll失败, 已退出!";
            exit(EPOLL_CTL_ERR);
        }
    }

    // 服务器启动
    void Start()
    {
        int timeout = -1; // 无限等待
        _isrunning = true;
        while (_isrunning)
        {
            int n = epoll_wait(_epfd, _revs, size, timeout); // 等待事件发生
            switch (n)
            {
            case 0:
                LOG(LogLevel::INFO) << "epoll_wait timeout, 等待事件超时!";
                break;
            case -1:
                LOG(LogLevel::ERROR) << "epoll_wait error, 等待事件发生错误!";
                break;
            default:
                Dispatcher(n); // 分派事件
                break;
            }
        }
        _isrunning = false;
    }

    void Dispatcher(int readynum)
    {
        LOG(LogLevel::INFO) << "event ready, Dispatcher called, epoll就绪事件数量: " << readynum;

        for (int i = 0; i < readynum; i++)
        {
            int sockfd = _revs[i].data.fd; // 事件发生的套接字
            uint32_t revents = _revs[i].events;

            // 读事件就绪
            if (revents & EPOLLIN)
            {
                if (sockfd == _listensock->Fd())
                {
                    // 新链接就绪
                    Accepter();
                }
                else
                {
                    // 普通连接就绪
                    Recver(sockfd);
                }
            }

            // // 写事件就绪
            // if(_revs[i].events & EPOLLOUT)
            // {

            // }
        }
    }

    // accept处理连接请求
    void Accepter()
    {
        InetAddr client;
        int sockfd = _listensock->Accept(&client); // 接受连接请求

        // 添加新sockfd到epoll
        struct epoll_event ev;
        ev.events = EPOLLIN; // 关注读事件
        ev.data.fd = sockfd;
        int n = epoll_ctl(_epfd, EPOLL_CTL_ADD, sockfd, &ev);

        if (n < 0)
        {
            LOG(LogLevel::WARNING) << "epoll_ctl error, 注册新连接到epoll失败!";
        }
        else
        {
            LOG(LogLevel::INFO) << "new sockfd accepted, fd: " << sockfd
                                << ", 客户端地址: " << client.StringAddr();
        }
    }

    
    // recv处理数据接收
    void Recver(int sockfd)
    {
        // 接收数据
        char buffer[1024];
        ssize_t n = recv(sockfd, buffer, sizeof(buffer) - 1, 0);
        buffer[n] = '\0'; // 添加字符串结束符

        if (n > 0)
        {
            // 成功接收数据
            std::cout << "client fd " << sockfd << " 发来数据: " << buffer << std::endl;
        }
        else if (n == 0)
        {
            // 客户端关闭连接
            LOG(LogLevel::INFO) << "客户端关闭连接, fd: " << sockfd;

            // 移除sockfd
            int ret = epoll_ctl(_epfd, EPOLL_CTL_DEL, sockfd, nullptr);
            if(ret == 0)
            {
                LOG(LogLevel::INFO) << "sockfd removed success, fd: " << sockfd;
            }
            
            close(sockfd); // 关闭连接
        }
        else
        {
            // 接收错误
            LOG(LogLevel::ERROR) << "接收错误, fd: " << sockfd;

            // 移除sockfd
            int ret = epoll_ctl(_epfd, EPOLL_CTL_DEL, sockfd, nullptr);
            if(ret == 0)
            {
                LOG(LogLevel::INFO) << "sockfd removed success, fd: " << sockfd;
            }
            
            close(sockfd); // 关闭连接
        }
    }


    // // 服务器停止
    // void Stop()
    // {
    //     _isrunning = false;
    // }

    // // 析构
    // ~EpollServer()
    // {
    //     _listensock->Close(); // 关闭监听套接字
    //     if (_epfd != defaultfd)
    //     {
    //         close(_epfd); // 关闭epoll句柄
    //     }
    // }

private:
    std::unique_ptr<Socket> _listensock; // 基类套接字
    bool _isrunning;                     // 运行状态
    int _epfd;                           // epoll句柄
    struct epoll_event _revs[size];      // epoll读就绪事件数组
};